package com.ecarx.module_log;


import android.graphics.Color;
import android.os.SystemProperties;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.app.ActivityCompat;

import com.ecarx.library_base.BaseApplication;
import com.ecarx.library_base.base_fragment.BaseFragment;
import com.ecarx.library_base.base_util.RotateAnimationUtil;
import com.ecarx.library_base.usb.UDiskDevice;
import com.ecarx.module_log.adapter.SpinnerAdapter;
import com.ecarx.module_log.adapter.TitleSpinnerAdapter;
import com.ecarx.module_log.controller.LogManagerController;
import com.ecarx.module_log.logexport.adapter.UsbDeviceAdapter;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;


public class LogControlFragment extends BaseFragment implements LogControlViewCallback, View.OnClickListener {
    private TextView mtvApLogStatus, mtvNetLogStatus, mtvBtLogStatus;
    private Button mBtnApLogOpen, mBtnNetLogOpen, mBtnBtLogOpen, mBtnlogClean, mBtnlogout, mBtnApLogClose, mBtnNetLogClose, mBtnBtLogClose;
    private Spinner mSpinnerLogLevel, mSpinnerUsb, mSpinnerLogSwitch, mSpinnerLogOut, mSpinnerLogClean;
    private TextView mTvLogCopyLoading, mTvLogOpenLoading;
    private ImageView mIvLogCopyLoading, mIvLogOpenLoading;
    private TextView mTvLogCleanLoading;
    private ImageView mIvLogCleanLoading;
    private UsbDeviceAdapter mUsbDeviceAdapter;
    private LinearLayout mLLLogcopySpinnerGroup, mLLLogcopyLoadingGroup;
    private LinearLayout mLLLogCleanLoadingGroup;
    private ConstraintLayout mClLogopenLoading;
    private LogManagerController mController;

    private SpinnerAdapter mLogLevelAdapter;

    public LogControlFragment() {
        // Required empty public constructor
    }

    @Override
    protected int layoutId() {
        return R.layout.fragment_log_control;
    }

    @Override
    protected void init(View view) {
        findViews(view);
        initListener();
        showOpenLogLoading(true);
        initSpinnerView();
        mController = new LogManagerController(this, getContext());
        mController.init();
        initDatas();
    }

    private void initSpinnerView() {
        initLevelSpinner();
        initControllerOSSpinner();
        initLogOutOSSpinner();
        initLogCleanOSSpinner();
    }

    private void initListener() {
        mBtnApLogOpen.setOnClickListener(this);
        mBtnApLogClose.setOnClickListener(this);
        mBtnBtLogOpen.setOnClickListener(this);
        mBtnBtLogClose.setOnClickListener(this);
        mBtnNetLogOpen.setOnClickListener(this);
        mBtnNetLogClose.setOnClickListener(this);
        mBtnlogClean.setOnClickListener(this);
        mBtnlogout.setOnClickListener(this);
    }

    private void initDatas() {
        // Add for MIDSPO-1269 mount hypervisor and cluster log partition before export SoC log by ECARX：liang.wan start
        // 启动日志分区服务
        try {
            SystemProperties.set("ctl.start", "mount_hypervisor");
        }catch (RuntimeException e) {
            Log.e(TAG, e.getMessage(), e);
        }

        try {
            SystemProperties.set("ctl.start", "mount_cluster");
        } catch (RuntimeException e) {
            Log.e(TAG, e.getMessage(), e);
        }

        try {
            SystemProperties.set("ctl.start", "mount_gameos");
        } catch (RuntimeException e) {
            Log.e(TAG, e.getMessage(), e);
        }
        // Add end

        setUsbAdapter();
        changeRecordStatus(mBtnNetLogOpen, mBtnNetLogClose, mtvNetLogStatus, mController.isNetRecording());
        changeRecordStatus(mBtnBtLogOpen, mBtnBtLogClose, mtvBtLogStatus, mController.isBtRecording());
    }


    private void setUsbAdapter() {
        List<UDiskDevice> uDiskDeviceList = mController.getUDiskDeviceList();
        mSpinnerUsb.post(() -> mSpinnerUsb.setDropDownVerticalOffset(mSpinnerUsb.getHeight()));
        mUsbDeviceAdapter = new UsbDeviceAdapter(uDiskDeviceList);
        mSpinnerUsb.setEnabled(!uDiskDeviceList.isEmpty());
        mBtnlogout.setEnabled(!uDiskDeviceList.isEmpty());
        mSpinnerUsb.setAdapter(mUsbDeviceAdapter);
    }

    /**
     * 日志开关中日志等级 选择下拉框
     */
    private void initLevelSpinner() {
        mSpinnerLogLevel.post(() -> mSpinnerLogLevel.setDropDownVerticalOffset(mSpinnerLogLevel.getHeight()));
        mLogLevelAdapter = new SpinnerAdapter();
        mSpinnerLogLevel.setAdapter(mLogLevelAdapter);
    }


    private void findViews(View view) {
        mIvLogOpenLoading = view.findViewById(R.id.iv_logopen_loading);
        mTvLogOpenLoading = view.findViewById(R.id.tv_logopen_loading);
        mtvApLogStatus = view.findViewById(R.id.tv_aplog_status);
        mtvBtLogStatus = view.findViewById(R.id.tv_btlog_status);
        mtvNetLogStatus = view.findViewById(R.id.tv_netlog_status);
        mBtnBtLogOpen = view.findViewById(R.id.btn_btlog_open);
        mBtnApLogOpen = view.findViewById(R.id.btn_aplog_open);
        mBtnNetLogOpen = view.findViewById(R.id.btn_netlog_open);
        mBtnApLogClose = view.findViewById(R.id.btn_aplog_close);
        mBtnNetLogClose = view.findViewById(R.id.btn_netlog_close);
        mBtnBtLogClose = view.findViewById(R.id.btn_btlog_close);
        mSpinnerLogLevel = view.findViewById(R.id.spinner);
        mBtnlogout = view.findViewById(R.id.btn_log_out_open);
        mBtnlogClean = view.findViewById(R.id.btn_log_clean_open);
        mSpinnerUsb = view.findViewById(R.id.spinner_usb);
        mIvLogCopyLoading = view.findViewById(R.id.iv_logcopy_loading);
        mTvLogCopyLoading = view.findViewById(R.id.tv_logcopy_loading);
        mIvLogCleanLoading = view.findViewById(R.id.iv_logclean_loading);
        mTvLogCleanLoading = view.findViewById(R.id.tv_logclean_loading);
        mLLLogcopySpinnerGroup = view.findViewById(R.id.ll_usb_spinner);
        mLLLogcopyLoadingGroup = view.findViewById(R.id.ll_logcopy_loading);
        mLLLogCleanLoadingGroup = view.findViewById(R.id.ll_logclean_loading);
        mClLogopenLoading = view.findViewById(R.id.ll_logopen_loading);
        mSpinnerLogSwitch = view.findViewById(R.id.spinner_log_swith);
        mSpinnerLogClean = view.findViewById(R.id.spinner_log_clean);
        mSpinnerLogOut = view.findViewById(R.id.spinner_log_out);
        mClLogopenLoading.setOnTouchListener((View v, MotionEvent event) -> true);  //蒙板拦截点击事件
    }


    @NonNull
    private TitleSpinnerAdapter getSpinnerAdapter(int spinner_title_switch, String extraString) {
        List<String> list = Arrays.asList(getResources().getStringArray(spinner_title_switch)).stream().map((s) -> s + extraString).collect(Collectors.toList());
        TitleSpinnerAdapter adapter = new TitleSpinnerAdapter(context);
        adapter.notifyData(list);
        return adapter;
    }


    /**
     * 日志导出view事件处理，
     * 日志导出结束后，结果界面五秒后消失
     *
     * @param isShow    显示loading
     * @param isSucceed 导出结果
     */
    public void showLogExportLoading(boolean isShow, boolean isSucceed) {
        mBtnlogout.post(new Runnable() {
            @Override
            public void run() {
                mLLLogcopyLoadingGroup.setVisibility(View.VISIBLE);
                mLLLogcopySpinnerGroup.setVisibility(View.GONE);
                if (isShow) {
                    mSpinnerLogOut.setEnabled(false);
                    mIvLogCopyLoading.setImageDrawable(AppCompatResources.getDrawable(BaseApplication.getInstance(), R.drawable.loading_bule));
                    mTvLogCopyLoading.setText(R.string.log_outing);
                    mTvLogCopyLoading.setTextColor(Color.BLUE);
                    mIvLogCopyLoading.setAnimation(RotateAnimationUtil.createRotateAnimation());
                    mBtnlogout.setEnabled(false);
                    mBtnlogClean.setEnabled(false);
                } else {
                    mIvLogCopyLoading.clearAnimation();
                    mIvLogCopyLoading.setImageDrawable(isSucceed ? AppCompatResources.getDrawable(BaseApplication.getInstance(), R.drawable.ic_succeed) : AppCompatResources.getDrawable(BaseApplication.getInstance(), R.drawable.ic_error));
                    mTvLogCopyLoading.setText(isSucceed ? R.string.log_out_finish : R.string.log_out_fail);
                    mTvLogCopyLoading.setTextColor(Color.BLACK);
                    mIvLogCopyLoading.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            mLLLogcopyLoadingGroup.setVisibility(View.GONE);
                            mLLLogcopySpinnerGroup.setVisibility(View.VISIBLE);
                            mBtnlogClean.setEnabled(true);
                            mSpinnerLogOut.setEnabled(true);
                            List<UDiskDevice> uDiskDeviceList = mController.getUDiskDeviceList();
                            mBtnlogout.setEnabled(!uDiskDeviceList.isEmpty());
                        }
                    }, 5000);
                }
            }
        });
    }

    /**
     * U盘数量改变回调
     *
     * @param isAdd
     * @param uDiskDeviceList
     */
    @Override
    public void onUsbChanged(boolean isAdd, List<UDiskDevice> uDiskDeviceList) {
        mSpinnerUsb.setEnabled(!uDiskDeviceList.isEmpty());
        mBtnlogout.setEnabled(!uDiskDeviceList.isEmpty());
        mUsbDeviceAdapter.notifyData(uDiskDeviceList);
    }

    /**
     * 改变蓝牙日志开关状态
     */
    @Override
    public void changBtRecordState() {
        changeRecordStatus(mBtnBtLogOpen, mBtnBtLogClose, mtvBtLogStatus, mController.isBtRecording());
    }

    @Override
    public void changApRecordState(boolean isRecording) {
        showOpenLogLoading(false);
        changeRecordStatus(mBtnApLogOpen, mBtnApLogClose, mtvApLogStatus, isRecording);
    }

    @Override
    public void changNetRecordState(boolean isRecording) {
        changeRecordStatus(mBtnNetLogOpen, mBtnNetLogClose, mtvNetLogStatus, mController.isNetRecording());
    }

    public void cleanLogs(boolean isCleaning, boolean cleanSuccess) {
        mBtnlogClean.post(new Runnable() {
            @Override
            public void run() {
                mLLLogCleanLoadingGroup.setVisibility(View.VISIBLE);
                if (isCleaning) {
                    mIvLogCleanLoading.setImageDrawable(AppCompatResources.getDrawable(BaseApplication.getInstance(), R.drawable.loading_bule));
                    mTvLogCleanLoading.setText(getString(R.string.log_cleaning));
                    mTvLogCleanLoading.setTextColor(Color.BLUE);
                    mSpinnerLogClean.setEnabled(false);
                    mIvLogCleanLoading.setAnimation(RotateAnimationUtil.createRotateAnimation());
                    mBtnlogClean.setEnabled(false);
                    // 日志清理中时，导出日志按钮置灰
                    mBtnlogout.setEnabled(false);
                } else {
                    mIvLogCleanLoading.clearAnimation();
                    mIvLogCleanLoading.setImageDrawable(cleanSuccess ? AppCompatResources.getDrawable(BaseApplication.getInstance(), R.drawable.ic_succeed) : AppCompatResources.getDrawable(BaseApplication.getInstance(), R.drawable.ic_error));
                    mTvLogCleanLoading.setText(cleanSuccess ? getString(R.string.log_clean_done) : getString(R.string.log_clean_failed));

                    mTvLogCleanLoading.setTextColor(Color.BLACK);
                    mIvLogCleanLoading.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            mLLLogCleanLoadingGroup.setVisibility(View.GONE);
                            mBtnlogClean.setEnabled(true);
                            mSpinnerLogClean.setEnabled(true);
                            // 日志清理结束后，导出日志按钮重置
                            mBtnlogout.setEnabled(!mController.getUDiskDeviceList().isEmpty());
                        }
                    }, 5000);
                }
            }
        });
    }

    @Override
    public void cleanLogFinish(boolean cleanSuccess) {
        cleanLogs(false, cleanSuccess);
    }

    @Override
    public void startCleanLog() {
        cleanLogs(true, false);
    }

    @Override
    public void unSupportCleanIsLogExporting() {
        showToast(getContext().getString(R.string.log_exporting_unable_clean));
    }

    @Override
    public void unSupportcleanIsLogCleaning() {
        showToast(getContext().getString(R.string.log_cleaning_unable_clean));
    }

    /**
     * 没有U盘
     */
    @Override
    public void noUDiskNotice() {
        showToast(getContext().getString(R.string.u_disk_not_found));
    }

    @Override
    public void unSupportExport() {
        getContext().getString(R.string.unsupport_export_out);
    }

    @Override
    public void startSetGuestOSLevel() {
        showOpenLogLoading(true);
    }

    @Override
    public void startLogExport() {
        showLogExportLoading(true, false);
    }

    @Override
    public void finishLogExport(boolean success) {
        showLogExportLoading(false, success);
    }

    @Override
    public void setUXOSLevelDataAndIndex(int index) {
        mLogLevelAdapter.notifyData(Arrays.asList(getResources().getStringArray(R.array.aplog_level_list)));
        setLevelSelect(index);
    }


    @Override
    public void setGuestOSLevelData(int index) {
        mLogLevelAdapter.notifyData(Arrays.asList(getResources().getStringArray(R.array.guest_level_list)));
        setLevelSelect(index);

    }

    @Override
    public void setControllerOSIndex(int index) {
        mSpinnerLogSwitch.setSelection(index, false);
    }

    public void initControllerOSSpinner() {
        mSpinnerLogSwitch.setAdapter(getSpinnerAdapter(R.array.spinner_title_switch, ""));
        mSpinnerLogSwitch.post(() -> mSpinnerLogSwitch.setDropDownVerticalOffset(mSpinnerLogSwitch.getHeight()));
        mSpinnerLogSwitch.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                Log.d(TAG, "setControllerOSIndex onItemSelected: position=" + position);
                showOpenLogLoading(true);
                mController.setControlLogOSType(position);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });
    }

    @Override
    public void setLogOutOSIndex(int index) {
        mSpinnerLogOut.setSelection(index, false);

    }

    public void initLogOutOSSpinner() {
        mSpinnerLogOut.setAdapter(getSpinnerAdapter(R.array.spinner_title_switch, getString(R.string.export_out)));
        mSpinnerLogOut.post(() -> mSpinnerLogOut.setDropDownVerticalOffset(mSpinnerLogOut.getHeight()));
        mSpinnerLogOut.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                mController.setLogOutType(position);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });
    }

    @Override
    public void setLogCleanOSIndex(int index) {
        mSpinnerLogClean.setSelection(index, false);

    }

    @Override
    public void cleanGuestLogFinish(boolean success) {
        cleanLogs(false,success);
    }

    public void initLogCleanOSSpinner() {
        mSpinnerLogClean.setAdapter(getSpinnerAdapter(R.array.clean_spinner_title_switch, getString(R.string.log_clear)));
        mSpinnerLogClean.post(() -> mSpinnerLogClean.setDropDownVerticalOffset(mSpinnerLogClean.getHeight()));
        mSpinnerLogClean.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                mController.setClearLogType(position);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });
    }


    private void setLevelSelect(int index) {
        mSpinnerLogLevel.setOnItemSelectedListener(null);
        mSpinnerLogLevel.setSelection(index, false);
        mSpinnerLogLevel.setEnabled(!mController.isApRecording());
        mSpinnerLogLevel.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                mController.changeRecordLevel(position);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });
    }

    @Override
    public void socketConnectFail() {
        setGuestOSLevelData(mController.getRecordLevelPosition());
        showToast(getContext().getString(R.string.connect_error));
        changApRecordState(false);
    }

    @Override
    public void cleanSocketConnectFail() {
        showToast(getContext().getString(R.string.connect_error));
        cleanLogs(false,true);
    }

    private void startNetLogRecord() {
        if (!mController.isNetRecording()) {
            mController.setNetRecording(true);
            mBtnNetLogOpen.setEnabled(false);
            showToast(getString(R.string.open_success));
            changeRecordStatus(mBtnNetLogOpen, mBtnNetLogClose, mtvNetLogStatus, mController.isNetRecording());
        }
    }

    public void changeRecordStatus(Button openBtn, Button closeBtn, TextView tv, boolean recording) {
        openBtn.setEnabled(!recording);
        tv.setText(recording ? R.string.opened : R.string.stoped);
        tv.setSelected(recording);
        tv.setCompoundDrawablePadding(0);
        tv.setCompoundDrawablesWithIntrinsicBounds(ActivityCompat.getDrawable(getActivity(), recording ? R.mipmap.success : R.mipmap.error), null, null, null);
        tv.setBackgroundColor(ActivityCompat.getColor(getActivity(), recording ? R.color.E7FFE9 : R.color.FFECE7));
        if (recording) {
            closeBtn.postDelayed(() -> closeBtn.setEnabled(recording), 1000);
        } else {
            closeBtn.setEnabled(recording);
        }
    }

    public void showOpenLogLoading(boolean isShow) {
        if (isShow) {
            mClLogopenLoading.setVisibility(View.VISIBLE);
            mIvLogOpenLoading.setImageDrawable(AppCompatResources.getDrawable(BaseApplication.getInstance(), R.drawable.loading_bule));
            mTvLogOpenLoading.setText(R.string.now_loading);
            mTvLogOpenLoading.setTextColor(Color.BLUE);
            mIvLogOpenLoading.setAnimation(RotateAnimationUtil.createRotateAnimation());
            mBtnApLogOpen.setEnabled(false);
            mBtnApLogClose.setEnabled(false);
        } else {
            mClLogopenLoading.setVisibility(View.GONE);
            mBtnApLogOpen.setEnabled(true);
            mIvLogOpenLoading.clearAnimation();
            mBtnApLogClose.setEnabled(true);
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mController.release();
    }


    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (id == R.id.btn_aplog_open) {
            if (!mController.isApRecording()) {
                showOpenLogLoading(true);
                mController.setCurOSRecording(true);
            }
        } else if (id == R.id.btn_aplog_close) {
            if (mController.isApRecording()) {
                showOpenLogLoading(true);
                mController.setCurOSRecording(false);
            }
        } else if (id == R.id.btn_btlog_open) {
            mController.setBtRecording(!mController.isBtRecording());
            changeRecordStatus(mBtnBtLogOpen, mBtnBtLogClose, mtvBtLogStatus, mController.isBtRecording());
        } else if (id == R.id.btn_btlog_close) {
            mController.setBtRecording(false);
            changeRecordStatus(mBtnBtLogOpen, mBtnBtLogClose, mtvBtLogStatus, mController.isBtRecording());
        } else if (id == R.id.btn_netlog_open) {
            startNetLogRecord();
        } else if (id == R.id.btn_netlog_close) {
            mController.stopNetlogRecord();
        } else if (id == R.id.btn_log_clean_open) {
            mController.clickCleanBtn();
        } else if (id == R.id.btn_log_out_open) {
            mController.logExport((UDiskDevice) mSpinnerUsb.getSelectedItem());
        }

    }

}